package com.tianyuan.test1;
/**
 * 滑动窗口
 */

/**
 * 无重复字符的最长子串
 *
 * @date 2025/10/27 16:01
 * 给定一个字符串 s ，请你找出其中不含有重复字符的 最长子串 的长度。
 * 示例1:
 * 输入: s = "abcabcbb"
 * 输出: 3
 * 解释: 因为无重复字符的最长子串是 "abc"，所以其长度为 3。注意 "bca" 和 "cab" 也是正确答案。
 * 示例 2:
 * 输入: s = "bbbbb"
 * 输出: 1
 * 解释: 因为无重复字符的最长子串是 "b"，所以其长度为 1。
 * 示例 3:
 * 输入: s = "pwwkew"
 * 输出: 3
 * 解释: 因为无重复字符的最长子串是"wke"，所以其长度为 3。
 * 请注意，你的答案必须是 子串 的长度，"pwke"是一个子序列，不是子串。
 */
import java.util.HashSet;
import java.util.Set;
//todo
class Solution {
    /**
     * 计算字符串中不含重复字符的最长子串的长度
     * @param s 输入的字符串
     * @return 最长无重复字符子串的长度
     */
    public int lengthOfLongestSubstring(String s) {
        // 哈希集合，用于记录当前窗口中已出现的字符，快速判断字符是否重复
        Set<Character> occ = new HashSet<Character>();
        int n = s.length(); // 字符串的长度
        // 右指针，初始值为 -1，表示初始时窗口右边界在字符串左边界的左侧（窗口为空）
        int rk = -1;
        int ans = 0; // 用于记录最长无重复子串的长度
        // 左指针 i 遍历字符串，作为窗口的左边界
        for (int i = 0; i < n; ++i) {
            if (i != 0) {
                // 左指针向右移动一格时，移除前一个位置的字符（滑动窗口左边界右移）
                occ.remove(s.charAt(i - 1));
            }
            // 不断移动右指针，扩展窗口，直到遇到重复字符或到达字符串末尾
            // 条件：右指针的下一位不越界，且下一位字符不在当前窗口中
            while (rk + 1 < n && !occ.contains(s.charAt(rk + 1))) {
                // 将下一位字符加入集合（标记为已在窗口中）
                occ.add(s.charAt(rk + 1));
                rk++; // 右指针右移
            }
            // 此时 [i, rk] 是当前左边界为 i 时的最长无重复子串
            // 更新最长长度（取当前最大值和新窗口长度的较大者）
            ans = Math.max(ans, rk - i + 1);
        }
        return ans;
    }









    public static void main(String[] args) {
        Solution solution = new Solution();

        // 示例1
        String s1 = "abcabcbb";
        int result1 = solution.lengthOfLongestSubstring(s1);
        System.out.println("示例1:");
        System.out.println("输入: s = \"" + s1 + "\"");
        System.out.println("输出: " + result1); // 预期 3
        System.out.println("解释: 无重复字符的最长子串是 \"abc\"（或\"bca\"、\"cab\"等），长度为 3\n");

        // 示例2
        String s2 = "bbbbb";
        int result2 = solution.lengthOfLongestSubstring(s2);
        System.out.println("示例2:");
        System.out.println("输入: s = \"" + s2 + "\"");
        System.out.println("输出: " + result2); // 预期 1
        System.out.println("解释: 无重复字符的最长子串是 \"b\"，长度为 1\n");

        // 示例3
        String s3 = "pwwkew";
        int result3 = solution.lengthOfLongestSubstring(s3);
        System.out.println("示例3:");
        System.out.println("输入: s = \"" + s3 + "\"");
        System.out.println("输出: " + result3); // 预期 3
        System.out.println("解释: 无重复字符的最长子串是 \"wke\"，长度为 3");
    }
}